/**
 * 
 */
package org.tio.sitexxx.im.server;

import java.util.Comparator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.ChannelContext;
import org.tio.sitexxx.im.server.utils.ImUtils;
import org.tio.sitexxx.service.model.main.User;
import org.tio.sitexxx.service.service.base.UserRoleService;
import org.tio.sitexxx.service.vo.Const;

import cn.hutool.core.util.StrUtil;

/**
	1、 自反性：x，y 的比较结果和 y，x 的比较结果相反。
	2、传递性：x>y,y>z,则 x>z。
	3、对称性：x=y,则 x,z 比较结果和 y，z 比较结果相同。
 * @author tanyaowu
 *
 */
public class ChannelContextComparator implements Comparator<ChannelContext> {
	//	@SuppressWarnings("unused")
	private static Logger log = LoggerFactory.getLogger(ChannelContextComparator.class);

	// = null时不排序
	public static final ChannelContextComparator me = null;//new ChannelContextComparator();

	private ChannelContextComparator() {
	}

	/**
	 * o2在前面请返回1
	 * o1在前面请返回-1
	 */
	@Override
	public int compare(ChannelContext o1, ChannelContext o2) {
		if (o1 == o2) {
			//			log.error("------------------俩ChannelContext对象是同一个对象");
			return 0;
		}

		User u1 = ImUtils.getHandshakeUser(o1);
		User u2 = ImUtils.getHandshakeUser(o2);

		if (u1 == null && u2 == null) { //都为null
			return compareWhenEqual(o1, o2);
		} else if (u1 != null && u2 == null) {
			return -1;
		} else if (u1 == null && u2 != null) {
			return 1;
		} else { //u1, u2都不为null
			boolean isDoc1 = UserRoleService.hasRole(u1, Const.Role.ALLOW_READ_DOC);
			boolean isDoc2 = UserRoleService.hasRole(u2, Const.Role.ALLOW_READ_DOC);

			if (isDoc1 && !isDoc2) {
				return -1;
			} else if (!isDoc1 && isDoc2) {
				return 1;
			}

			return compareWhenEqual(o1, o2);
		}
	}

	/**
	 * 当都为游客或为同一个用户时
	 * o2在前面请返回1
	 * o1在前面请返回-1
	 */
	private int compareWhenEqual(ChannelContext o1, ChannelContext o2) {
		String cid1 = o1.getId();
		String cid2 = o2.getId();
		int ret = StrUtil.compare(cid1, cid2, false);
		if (ret > 0) {
			return 1;
		} else if (ret < 0) {
			return -1;
		} else {
			log.error("ChannelContext.id[{}][{}]竟然一样", cid1, cid2);

		}
		return ret;

	}
}
